﻿using agsXMPP;
using agsXMPP.protocol.client;
using agsXMPP.protocol.iq.disco;
using agsXMPP.protocol.iq.roster;
using agsXMPP.protocol.x.data;
using agsXMPP.Xml.Dom;
using IMDemo.Models;
using IMDemo.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace IMDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        #region 字段
        private XmppClientConnection xmppClient;
        #endregion

        public MainWindow()
        {
            this.InitializeComponent();
            this.Loaded += this.MainWindow_Loaded;
            this.Closed += MainWindow_Closed;
            this.ucContactList.SendMessage += UcContactList_SendMessage;
            this.ucGroupList.SendMessage += UcGroupList_SendMessage;
        }

        #region 事件处理
        #region 窗体关闭事件
        private void MainWindow_Closed(object sender, EventArgs e)
        {
            this.Exit();
        }
        #endregion

        #region 窗体加载事件
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            this.Login();
        }
        #endregion

        #region 打开消息对话框
        private void UcContactList_SendMessage(object sender, ContactModel to)
        {
            UCDialog ucDialog = this.ucDialogList.Dialogs.Where(p => p.DialogType == 0).FirstOrDefault(p => p.Contacter.ContactJid.Bare == to.ContactJid.Bare);
            if (ucDialog == null)
            {
                ucDialog = new Views.UCDialog(this.xmppClient, to, 0);
                this.ucDialogList.Dialogs.Insert(0, ucDialog);
            }

            this.ucDialogList.SelectedDialog = ucDialog;
            this.tiDialog.IsSelected = true;
        }
        #endregion

        #region 打开群组对话框
        private void UcGroupList_SendMessage(object sender, ContactModel to)
        {
            UCDialog ucDialog = this.ucDialogList.Dialogs.Where(p => p.DialogType == 1).FirstOrDefault(p => p.Contacter.ContactJid.Bare == to.ContactJid.Bare);
            if (ucDialog == null)
            {
                ucDialog = new Views.UCDialog(this.xmppClient, to, 1);
                this.ucDialogList.Dialogs.Insert(0, ucDialog);
            }

            this.ucDialogList.SelectedDialog = ucDialog;
            this.tiDialog.IsSelected = true;
        }
        #endregion

        #region 接收消息
        /// <summary>
		/// We received a message
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="msg"></param>
		private void xmppClient_OnMessage(object sender, agsXMPP.protocol.client.Message msg)
        {
            if (msg.Type == MessageType.error)
            {
                log4net.LogManager.GetLogger(this.GetType()).Error(msg.Error);
                return;
            }

            // check for xData Message

            if (msg.HasTag(typeof(Data)))
            {
                return;
            }
            else if (msg.HasTag(typeof(agsXMPP.protocol.extensions.ibb.Data)))
            {
                return;
            }
            else
            {
                if (msg.Body != null)
                {
                    this.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        ContactModel contact = this.ucContactList.ContactList.FirstOrDefault(p => p.ContactJid.Bare == msg.From.Bare);
                        if (contact == null)
                        {
                            contact = this.ucGroupList.GroupList.FirstOrDefault(p => p.CurrentGroup.ContactJid.Bare == msg.From.Bare).CurrentGroup;
                            if (contact == null)
                            {
                                return;
                            }
                        }

                        MessageModel model = new Models.MessageModel()
                        {
                            From = new Models.ContactModel()
                            {
                                ContactJid = contact.ContactJid,
                                ContactName = msg.Type == MessageType.groupchat ? msg.From.Resource : contact.ContactName
                            },
                            Contact = contact,
                            Msg = msg
                        };

                        UCDialog dialog = this.ucDialogList.Dialogs.FirstOrDefault(p => p.Contacter.ContactJid.Bare == msg.From.Bare);
                        if (dialog == null)
                        {
                            UCDialog ucDialog = new UCDialog(this.xmppClient, model.Contact, msg.Type == MessageType.groupchat ? 1 : 0);
                            ucDialog.MessageList.Add(model);
                            this.ucDialogList.Dialogs.Insert(0, ucDialog);
                            this.ucDialogList.SelectedDialog = ucDialog;
                        }
                        else
                        {
                            dialog.MessageList.Add(model);
                            if (!this.ucDialogList.SelectedDialog.Equals(dialog))
                            {
                                dialog.NoReadMessageList.Add(model);
                            }
                        }
                    }));
                }
            }
        }
        #endregion

        #region 登录成功
        private void xmppClient_OnLogin(object sender)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                Config.LoginUser = this.xmppClient.MyJID;
                this.sbUserName.Content = this.xmppClient.MyJID.User;
                this.sbStatus.Content = "在线";
            }));
            this.LoadGroupList();
        }
        #endregion

        #region 注销
        private void xmppClient_OnClose(object sender)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                this.sbUserName.Content = "xxx";
                this.sbStatus.Content = "离线";
            }));
        }
        #endregion

        #region 联系人相关事件
        private void xmppClient_OnRosterStart(object sender)
        {
        }

        private void xmppClient_OnRosterEnd(object sender)
        {
        }

        private void xmppClient_OnRosterItem(object sender, agsXMPP.protocol.iq.roster.RosterItem item)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (item.Subscription != SubscriptionType.remove)
                {
                    if (this.ucContactList.ContactList.FirstOrDefault(p => p.ContactJid.Bare == item.Jid.Bare) == null)
                    {
                        Models.ContactModel contact = new Models.ContactModel()
                        {
                            ContactName = item.Name,
                            ContactJid = item.Jid
                        };
                        this.ucContactList.ContactList.Add(contact);
                    }
                }
                else
                {
                    // 移除联系人
                }
            }));
        }
        #endregion

        #region 错误日志
        private void xmppClient_OnError(object sender, Exception ex)
        {
            log4net.LogManager.GetLogger(this.GetType()).Error(ex);
        }
        #endregion

        #region OnPresence
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="pres"></param>
        private void xmppClient_OnPresence(object sender, Presence pres)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (pres.Type == PresenceType.subscribe)
                {
                }
                else if (pres.Type == PresenceType.subscribed)
                {

                }
                else if (pres.Type == PresenceType.unsubscribe)
                {

                }
                else if (pres.Type == PresenceType.unsubscribed)
                {

                }
                else
                {
                }
            }));

        }
        #endregion

        #region 登录失败
        /// <summary>
        /// 登录失败
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void xmppClient_OnAuthError(object sender, Element e)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (this.xmppClient.XmppConnectionState != XmppConnectionState.Disconnected)
                    this.xmppClient.Close();

                MessageBox.Show("Authentication Error!\r\nWrong password or username.",
                    "Error",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
            }));
        }
        #endregion

        #region 验证证书
        private bool ClientSocket_OnValidateCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
        #endregion
        #endregion

        #region 方法
        #region 登录
        private void Login()
        {
            this.InitConnect();
            LoginWindow loginWindow = new IMDemo.LoginWindow(this.xmppClient);
            loginWindow.DataContext = this;
            loginWindow.Owner = this;
            if (loginWindow.ShowDialog().Value)
            {
                this.xmppClient.Open();
            }
            else
            {
                this.Close();
            }
        }
        #endregion

        #region 关闭
        private void Exit()
        {
            if (this.xmppClient != null)
            {
                this.xmppClient.Close();
            }
        }
        #endregion

        #region 加载群组列表
        private void LoadGroupList()
        {
            DiscoItemsIq discoIq = new DiscoItemsIq(IqType.get);
            discoIq.To = new Jid("conference.growing.com");
            this.xmppClient.IqGrabber.SendIq2(discoIq, new IqCB(OnGetChatRooms), null);
        }

        /// <summary>
        /// Callback
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="iq"></param>
        /// <param name="data"></param>
        private void OnGetChatRooms(object sender, IQ iq, object data)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                DiscoItems items = iq.Query as DiscoItems;
                if (items == null)
                    return;

                DiscoItem[] rooms = items.GetDiscoItems();
                List<ContactModel> list = new List<Models.ContactModel>();
                foreach (DiscoItem item in rooms)
                {
                    ContactModel model = new Models.ContactModel()
                    {
                        ContactJid = item.Jid,
                        ContactName = item.Name
                    };
                    list.Add(model);
                }

                this.ucGroupList.LoadGroupList(this.xmppClient, list);
            }));
        }
        #endregion

        #region InitConnect
        private void InitConnect()
        {
            try
            {
                this.xmppClient = new XmppClientConnection();

                this.xmppClient.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;

                this.xmppClient.OnRosterStart += new ObjectHandler(this.xmppClient_OnRosterStart);
                this.xmppClient.OnRosterEnd += new ObjectHandler(this.xmppClient_OnRosterEnd);
                this.xmppClient.OnRosterItem += new agsXMPP.XmppClientConnection.RosterHandler(this.xmppClient_OnRosterItem);

                this.xmppClient.OnLogin += new ObjectHandler(this.xmppClient_OnLogin);
                this.xmppClient.OnClose += new ObjectHandler(this.xmppClient_OnClose);
                this.xmppClient.OnError += new ErrorHandler(this.xmppClient_OnError);
                this.xmppClient.OnPresence += new PresenceHandler(this.xmppClient_OnPresence);
                this.xmppClient.OnMessage += new MessageHandler(this.xmppClient_OnMessage);
                this.xmppClient.OnAuthError += new XmppElementHandler(this.xmppClient_OnAuthError);
                this.xmppClient.OnSocketError += new ErrorHandler(this.xmppClient_OnError);

                this.xmppClient.ClientSocket.OnValidateCertificate += new System.Net.Security.RemoteCertificateValidationCallback(ClientSocket_OnValidateCertificate);
            }
            catch (Exception ex)
            {
                log4net.LogManager.GetLogger(this.GetType()).Error(ex);
            }
        }
        #endregion
        #endregion
    }
}
